#!/bin/bash
# FileName : runDiag
# Function : Bash script to install the Broadcom diagnostics dirver and
#            then run the Linux diagnostics

displayScriptVersion()
{
echo "Broadcom Linux Diagnostics Script v226.03 02/01/2023"
}

usage()
{
echo "NAME"
echo "        $0 - executes the Broadcom Linux Diagnostic"
echo ""
echo "SYNOPSIS"
echo "        $0 [-h] [-n] [--help] [--silent] [--drvrsRm] [--drvrsKeep]"
echo "                  [--drvrNoMk] [--norun]"
echo "        $0 [-sysop -l logfile -logfl]"
echo "        $0 [-sysop -c <devstart>-<devend> -e manuName -lapp logfile -logfl]"
echo "        $0 [-t <TestsString> -c <devstart>-<devend> -e manuName -fnvm fwfilename]"
echo "        $0 [-t <TestsString> -c <devstart>-<devend> -e manuName -fnvm fwfilename -m -automac]"
echo "        $0 [-sysop -t <TestsString> -c <devstart>-<devend> -e manuName -fnvm fwfilename -m -automac -l logfile]"
echo "        $0 [-sysop -t <TestsString> -c <devstart>-<devend> -e manuName -fnvm fwfilename -fmac <MACFile> -l logfile]"
echo ""
echo "DISCRIPTION"
echo "        -h           displays this help screen"
echo "        --help       displays this help screen"
echo "        --silent     reduces screen output"
echo "        --drvrsRm    remove installed drivers without prompting"
echo "        --drvrsKeep  keep installed drivers without prompting"
echo "                     has precedence over --drvrsRm"
echo "        --drvrsNoMk  do not make the dirver, use the previous make"
echo "        -n           do not make the dirver, use the previous make"
echo "        --norun      do not execute b57ldiag. To prepare the environment only"
echo "        -sysop       excecute sysop tests in manufacturing mode"
echo "        -t           program the nvram in manufacturing mode"
echo ""
}

verbose=1
reqDrvrsRm=0
reqDrvrsKeep=0
reqDrvrsMake=1
OldIfName=unknown
reqDiagRun=1

while [ $# -ge 1 ]; do
  case $1 in
    --drvrsRm)    reqDrvrsRm=1;;
    --drvrsKeep)  reqDrvrsKeep=1;;
    --drvrsNoMk)  reqDrvrsMake=0;;
    -n)           reqDrvrsMake=0;;
    --silent )    verbose=0;;
    --norun)      reqDiagRun=0;;
    -sysop)       break;;
    -t)           break;;
    --help)       usage; exit 1;;
    -h)           usage; exit 1;;
    *)            usage; exit 1;;
  esac
  shift
done

drvrsFound()
{
  count=0
  drvrsPresent=0;
  for drvr in ${drvrNames[@]}; do
    present=`lsmod | grep ${drvr} | awk '{print $1}' | grep ${drvr}`
    if [ "x${present}" == "x${drvr}" ]; then
      drvrPresent[$count]=1;
      drvrsPresent=$(( $drvrsPresent + 1  ));
    else
      drvrPresent[$count]=0;
    fi
    count=$(( $count + 1 ))
  done
  
  if [ $verbose == 1 ]; then
    if [ $drvrsPresent == 0 ]; then
      echo "No driver presently installed for Broadcom NetXtreme Chips"
    else
      count=0
      while [ "x${drvrNames[$count]}" != "x" ]; do
        if [ ${drvrPresent[$count]} == 1 ]; then
          echo "...${drvrNames[$count]} driver present"
        fi
        count=$(( $count + 1 ))
      done
    fi
  fi
}

drvrsRm()
{
  if [ $drvrsPresent == 0 ] ; then
    return; 
  fi
  
  if [ $reqDrvrsKeep == 1 ]; then
    return; 
  fi
  
  if [ $reqDrvrsRm == 0 ]; then
    echo "Enter \"c\" to remove driver(s) and continue"
    echo "            any other values exits the run"
    read continueRun
    if [ "x$continueRun" != "xc" ]; then
      echo "Exited Broadcom diagnostic run."
      exit 1;
    fi
  fi

  unameStr=`uname -r`
  kernelVer=${unameStr:0:3}
  if [ $kernelVer == "2.4" ]; then
    diagDrvrIfUpDown down;
  fi
 
  count=0 
  drvrsRms=""
# for crazy people who load more than one driver 
# remove all except for last driver which is remove just
# before insmod-ing the new driver 
# rmmod just before insmod to beat auto insmod of a driver
  for drvrHere in ${drvrPresent[@]}; do
    if [ $drvrHere == 1 ]; then
      if [ $drvrsPresent == 1 ]; then
        drvrsRms="${drvrNames[$count]}" 
      else
        drvrsPresent=$(( $drvrsPresent - 1 ))
        rmmod ${drvrNames[$count]}
        if [ $verbose == 1 ]; then
          echo "...rmmod ${drvrNames[$count]}"
        fi
      fi
    fi
    count=$(( $count + 1 ))
  done

  drvrsRms="rmmod $drvrsRms"
  if [ "x$1" == "xforce" ]; then
    if [ $verbose == 1 ]; then
      echo "...$drvrsRms"
    fi
    $drvrsRms
  fi
}


checkExists()
{
  if [ -e $1 ]; then
    if [ $verbose == 1 ]; then
      if [ -d $1 ]; then
        echo "...found $1 directory"
      else 
        echo "...found $1 file"
      fi 
    fi 
  else
    echo "...can not find $1 in `pwd`"
    echo "Enter \"c\" to continue running diagnostics"
    echo "            any other values exits the run"
    read continueRun
    if [ "x$continueRun" == "xc" ]; then
      if [ $verbose == 1 ]; then
        echo "Countinuing to run diagnostic without $1"
      fi 
    else
      echo "Exited Broadcom diagnostic run."
      exit 1
    fi
  fi
}

diagDrvrMake()
{
  if [ $reqDrvrsKeep == 1 ]; then
    return; 
  fi
  
  drvrRootFullName=${drvrRootName}-${drvrRootVersion}
  drvrRootTarZip=${drvrRootFullName}.tar.gz
  tar -xzf $drvrRootTarZip
  cd ${drvrPatchName}-${drvrRootVersion}
  make BCM_LX_DIAG=1
  cp  ${drvrPatchName}.ko ${dirStart}
  cp  ${drvrPatchName}.o ${dirStart}
  cd ${dirStart}
  rm -fr  ${drvrPatchName}-${drvrRootVersion}
    
  #tmpDrvrTar=drvr.tar
  #tmpDrvrTarZip=${tmpDrvrTar}.gz
  #drvrRootFullName=${drvrRootName}-${drvrRootVersion}
  #drvrRootTarZip=${drvrRootFullName}.tar.gz
  #drvrPatchFullName=${drvrPatchName}-${drvrPatchVersion}

# 1-copy the tg3 files (tg3.[ch], Makefile) from the Broadcom distributed 
#  tg3 source directory to a working directory containing the tg3d files.
#	eg. cp tg3-3.66i/* ../tg3d-0.02/.

  #tmpPatch=patch.tgz
  #checkExists ${drvrPatchFullName}.tgz
  #cp ${drvrPatchFullName}.tgz $tmpPatch
  #tar -xzf $tmpPatch
  #rm -rf $tmpPatch

  #checkExists $drvrRootTarZip
  #cp $drvrRootTarZip $tmpDrvrTarZip
  #gunzip -f $tmpDrvrTarZip
  #rm -rf $drvrRootFullName
  #tar -xf $tmpDrvrTar
  #rm -rf $tmpDrvrTar
  #cp $drvrRootFullName/* ${drvrPatchFullName}/
  #rm -rf $drvrRootFullName

#2-go to the working directory eg. cd tgd-0.02.
  #cd ${drvrPatchFullName}
#  cp ../tg3_patch .
#3-run setup.sh.
  #checkExists setup.sh
  #chmod 777 setup.sh
  #./setup.sh

#4-make the new tg3d file by invoking "make"
  #make
  #cp  ${drvrPatchName}.ko ${dirStart}
  #cp  ${drvrPatchName}.o ${dirStart}
  #cd ${dirStart}
  #rm -fr ${drvrPatchFullName}

}

diagDrvrInsmod()
{
  unameStr=`uname -r`
  kernelVer=${unameStr:0:3}
  kernelMajorVer=${unameStr:0:1}
  if [ $kernelVer == "2.6" ]; then
    drvrImg=${drvrPatchName}.ko
  elif [ $kernelMajorVer == "3" ]; then
    drvrImg=${drvrPatchName}.ko
  elif [ $kernelMajorVer -gt 3 ]; then
    drvrImg=${drvrPatchName}.ko
  else
    drvrImg=${drvrPatchName}.o
  fi
  modprobe hwmon
  modprobe ptp
  checkExists $drvrImg
  insmod="insmod $drvrImg"
  
  if [ $verbose == 1 ]; then
    if [ "x" != "x${drvrsRms}" ]; then 
      echo "...${drvrsRms}"
    fi
    echo "...${insmod}"
  fi

  ${drvrsRms}
  ${insmod}

  echo "...Waiting for a moment till all the interfaces are populated"
  sleep 10
   
}

diagOpensslVersion()
{
  opensslVer=`openssl version | awk -F - '{print $1}' | awk '{print $2}'`
  opensslTitle=`openssl version | awk '{print $1}'`
  if [ $opensslTitle == "OpenSSL" ]; then
    if [ $opensslVer != "0.9.8" ]; then
      ### Link libssl 
      opensslLibStr=/$1/libssl.so.${opensslVer}
      opensslLibLink=/usr/$1/libssl.so.0.9.8
      if [ -e $opensslLibLink ]; then
        echo "...$opensslLibLink exists"
      else  
        if [ -e $opensslLibStr ]; then
          lnopenssl="ln -sf $opensslLibStr $opensslLibLink"
        else
          lnopenssl="ln -sf /usr$opensslLibStr $opensslLibLink"
        fi  
        echo "...${lnopenssl}"
        ${lnopenssl}
      fi
      ### Link libcrypto
      opensslLibStr=/$1/libcrypto.so.${opensslVer}
      opensslLibLink=/usr/$1/libcrypto.so.0.9.8
      if [ -e $opensslLibLink ]; then
        echo "...$opensslLibLink exists"
      else  
        if [ -e $opensslLibStr ]; then
          lnopenssl="ln -sf $opensslLibStr $opensslLibLink"
        else
          lnopenssl="ln -sf /usr$opensslLibStr $opensslLibLink"
        fi
         echo "...${lnopenssl}"
        ${lnopenssl}
      fi
    else
      echo "...`openssl version`"
    fi
  else
    echo "...OpenSSL not installed. Please install OpenSSL 0.9.8 or later"
    exit 1
  fi
}

diagOpensslRemoveSymbolicLink()
{
  libStr=/usr/$1/libssl.so.0.9.8
  if [ -e $libStr ]; then
    cmdlsStr=`ls -l ${libStr}`
    isSymbolic=${cmdlsStr:0:1}
    ### Is a symbolic link ? ###
    if [ $isSymbolic == "l" ]; then
      ### Remove libssl ###
      rm $libStr
      echo "...Remove symbolic link ${libStr}"
      ### Remove libcrypto ###
      libStr=/usr/$1/libcrypto.so.0.9.8
      if [ -e $libStr ]; then
        cmdlsStr=`ls -l ${libStr}`
        isSymbolic=${cmdlsStr:0:1}
        ### Is a symbolic link ? ###
        if [ $isSymbolic == "l" ]; then
          rm $libStr
          echo "...Remove symbolic link ${libStr}"
        fi
      fi 
    fi
  fi
}
diagSaveFile()
{
  if [ -e $MODPROBE_FILE ]; then
    cp $MODPROBE_FILE $MODPROBE_FILE.brcm  
    echo "...backup $MODPROBE_FILE"
    rm $MODPROBE_FILE
  fi
}

diagRestoreSaveFile()
{
  if [ -e $MODPROBE_FILE.brcm ]; then
    echo "...restore $MODPROBE_FILE"
    cp $MODPROBE_FILE.brcm $MODPROBE_FILE
    rm $MODPROBE_FILE.brcm      
  fi
}

diagIgnoreNetworkManager()
{
  COUNT=0
  if [ -e $TARGET_FILE ]; then
    cp $TARGET_FILE $TARGET_FILE.brcm  
    echo "...backup $TARGET_FILE"
  else
    echo "...create $TARGET_FILE"
  fi 
#lshal | grep -A6 'Networking Interface' | awk -F "'" '/info.udi = / {print $2}'
#lshal | grep -B3 'Broadcom Corporation' | awk -F "'" '/info.udi = / {print $2}'
  printf "[keyfile]\n" > $TARGET_FILE
  for i in `lshal | grep -B3 'Broadcom Corporation' | awk -F "'" '/info.udi = / {print $2}'`; do
    if [ $COUNT == 0 ]; then
      COUNT=$COUNT+1;
      echo -n "unmanaged-devices=$i" >> $TARGET_FILE
    else
      echo -n ";$i" >> $TARGET_FILE
    fi
  done
  printf "\n" >> $TARGET_FILE
}

diagRestoreNetworkManager()
{
  if [ -e $TARGET_FILE.brcm ]; then
    echo "...restore $TARGET_FILE"
    cp $TARGET_FILE.brcm $TARGET_FILE
    rm $TARGET_FILE.brcm
  else
    echo "...remove $TARGET_FILE"
    rm $TARGET_FILE
  fi
}
diagBiosDevName()
{
  if [ $1 == "enable" ]; then
    if [ -e $BIOSDEVNAME.brcm ]; then
      echo "...enable biosdevname"
      mv $BIOSDEVNAME.brcm $BIOSDEVNAME
    fi
    if [ -e $NET_RULES.brcm ]; then
      mv -f $NET_RULES.brcm $NET_RULES
      echo "...restore $NET_RULES"
    else
      if [ -e $NET_RULES ]; then
        rm -f $NET_RULES
      fi
    fi
  elif [ $1 == "disable" ]; then
    if [ -e $NET_RULES ]; then
      if [ -e $NET_RULES.brcm ]; then
        echo "...$NET_RULES.brcm exists"
      else
        cp $NET_RULES $NET_RULES.brcm
        echo "...backup $NET_RULES"
      fi
    else
        echo "...$NET_RULES doesnt exist"
    fi
    if [ -e $BIOSDEVNAME ]; then
      echo "...disable biosdevname"
      mv $BIOSDEVNAME $BIOSDEVNAME.brcm
    fi
  fi
}

diagResumeIfName()
{

 # eths=`ifconfig -a | grep Ethernet | awk '{print $1}'`
  eths=`ip link | grep Ethernet | awk '{print $1}'`
  for eth in $eths; do
    if [ x${eth:0:3} == "xbcm" ]; then
      if [ x$OldIfName == "xeth" ]; then
        nic=`echo $eth | sed 's/bcm/eth/g'`
#      elif [ x$OldIfName == "xem" ]; then
#        nic=`echo $eth | sed 's/bcm/em/g'`
#      elif [ x$OldIfName == "xpm" ]; then
#        nic=`echo $eth | sed 's/bcm/pm/g'`
      else
        # By default, rename back to eth
        nic=`echo $eth | sed 's/bcm/eth/g'`
      fi
      if ! [ -x "$(command -v ifconfig)" ]; then
	ip link set $eth down
      else
	ifconfig $eth down
      fi
      ip link set $eth name $nic
      echo ...Rename $eth back to $nic
    fi
  done
}

diagDrvrIfUpDown()
{
  bcmcount=0

  if ! [ -x "$(command -v ifconfig)" ]; then
	echo 'ifconfig is not installed.' >&2
	echo "Using ip tool"
	eths=`ip addr | grep mtu | awk '{print $2}'`
	eths=`echo $eths | sed 's/://g'`
  else
	iftoolver=`ifconfig lo | grep flags | awk '{print $3}'`

	if [ x${iftoolver:0:3} == "xmtu" ]; then
		eths=`ifconfig -a | grep flags | awk '{print $1}'`
		eths=`echo $eths | sed 's/://g'`
		echo "ifconfig Version 2.10"
	else
	    eths=`ifconfig -a | grep Ethernet | awk '{print $1}'`
	    echo "ifconfig Version 1.6"
	fi
  fi

  for eth in $eths; do
    ethStr=`ethtool -i $eth`
    if [ x${ethStr:0:6} == "xdriver" ]; then
      ethStr=`echo $ethStr | awk '{ print $2 }'`
      count=0
      for drvrHere in ${drvrPresent[@]}; do
        if [ $ethStr == ${drvrNames[$count]} ]; then
          if [ $1 == "up" ]; then
            #
            # Rename the interface name to avoid bringing eth0 down
            # by kernel because of any failure to setup network configuration.
            # 03/27/2012 -thsiao-
            #
            # Disable biosdevname to avoid renaming eth to others. So, consider eth only.
            # 04/12/2012 -thsiao-

            if [ x${eth:0:3} == "xeth" ]; then
              nic=`echo $eth | sed 's/eth/bcm1/g'`
              OldIfName=eth
            elif [ x${eth:0:2} == "xem" ]; then
              nic=`echo $eth | sed 's/em/bcm2/g'`
              OldIfName=em
            elif [ x${eth:0:3} == "xeno" ]; then
              nic=`echo $eth | sed 's/eno/bcm3/g'`
              OldIfName=eno
            elif [ x${eth:0:3} == "xens" ]; then
              nic=`echo $eth | sed 's/ens/bcm4/g'`
              OldIfName=ens
 
            else
              nic=bcm5$bcmcount
              bcmcount=$(( $bcmcount + 1 ))
#            elif [ x${eth:0:2} == "xpm" ]; then
#              nic=`echo $eth | sed 's/pm/bcm/g'`
#              OldIfName=pm
            fi
	    if ! [ -x "$(command -v ifconfig)" ]; then
		ip link set $eth down
	    else
		ifconfig $eth down
	    fi
            ip link set $eth name $nic
	    if ! [ -x "$(command -v ifconfig)" ]; then
		ip link set $nic up
		echo "...ip link set $nic($eth) up"
	    else
		ifconfig $nic up
		echo "...ifconfig $nic($eth) up"
	    fi
          elif [ $1 == "down" ]; then
	    if ! [ -x "$(command -v ifconfig)" ]; then
		ip link set $eth down
		echo "...ip link set $eth down"
	    else
		ifconfig $eth down
		echo "...ifconfig $eth down"
	    fi
          else
            echo "...Oops, program error with diagDrvrIfUpDown"
            exit 1
          fi
        fi
        count=$(( $count + 1 ))
      done      
    else
      echo "...could not get driver information for $eth"
    fi
  done
}

diagOpensslLink()
{
# $1 : {b57ldiagi, b57ldiagi64, b57ldiagp}
# $2 : {ssl, crypto}
  LibNotFound=`ldd ./$1 | grep "lib$2.so" | grep "not found" | awk -F "=>" '{print $1}' | tr -d [:space:]` 
  if [ x$LibNotFound != "x" ]; then # lib$2 wasn't found, must make a success symboliclink for it.
    # Decide what is the version of library
    if [ $1 == "b57ldiagp" ]; then
      libver="libc6,64bit"
    elif [ $1 == "b57ldiagple" ]; then
      libver="libc6,64bit"
    elif [ $1 == "b57ldiagi" ]; then
      libver="libc6"
    else
      libver="libc6,x86-64"
    fi
    # figure out the shared object of the library (libssl and libcrypto)
    LibToLink=`ldconfig -p | grep "lib$2.so" | grep $libver | awk -F "=> " '{print $2;exit}'`
    if [ x$LibToLink != "x" ]; then
      LibPath=`echo $LibToLink | awk -F "lib$2.so" '{print $1}'`
      action="ln -sf $LibToLink $LibPath$LibNotFound"
    else
      action="lib$2 not found by ldconfig"
    fi
  echo "...${action}"
  ${action}  
  fi
}


diagOpenSSLCreateSymLink()
{
  machine=`uname -m`
  case $machine in
    ppc64)    diagOpensslLink b57ldiagp ssl;diagOpensslLink b57ldiagp crypto;;
    ppc64le)    diagOpensslLink b57ldiagple ssl;diagOpensslLink b57ldiagple crypto;;
    i386)     diagOpensslLink b57ldiagi ssl;diagOpensslLink b57ldiagi crypto;;
    i486)     diagOpensslLink b57ldiagi ssl;diagOpensslLink b57ldiagi crypto;;
    i586)     diagOpensslLink b57ldiagi ssl;diagOpensslLink b57ldiagi crypto;;
    i686)     diagOpensslLink b57ldiagi ssl;diagOpensslLink b57ldiagi crypto;;
    x86_64)   diagOpensslLink b57ldiagi64 ssl;diagOpensslLink b57ldiagi64 crypto;;
    aarch64)   diagOpensslLink b57ldiaga ssl;diagOpensslLink b57ldiaga crypto;;
    *)        echo "Unknown machine architecture - $machine"; exit 1;;
  esac
}


diagOpenSSLReLink()
{
  machine=`uname -m`
  case $machine in
    ppc64)    diagOpensslVersion lib64;;
    ppc64le)    diagOpensslVersion lib64;;
    i386)     diagOpensslVersion lib;;
    i486)     diagOpensslVersion lib;;
    i586)     diagOpensslVersion lib;;
    i686)     diagOpensslVersion lib;;
    x86_64)   diagOpensslVersion lib64;;
    aarch64)   diagOpensslVersion lib64;;
    *)        echo "Unknown machine architecture - $machine"; exit 1;;
  esac
}

diagOpenSSLRemoveLink()
{
  machine=`uname -m`
  case $machine in
    ppc64)    diagOpensslRemoveSymbolicLink lib64;;
    ppc64le)    diagOpensslRemoveSymbolicLink lib64;;
    i386)     diagOpensslRemoveSymbolicLink lib;;
    i486)     diagOpensslRemoveSymbolicLink lib;;
    i586)     diagOpensslRemoveSymbolicLink lib;;
    i686)     diagOpensslRemoveSymbolicLink lib;;
    x86_64)   diagOpensslRemoveSymbolicLink lib64;;
    aarch64)   diagOpensslRemoveSymbolicLink lib64;;
    *)        echo "Unknown machine architecture - $machine"; exit 1;;
  esac
}

diagRun()
{
  cd $dirStart
  machine=`uname -m`
  case $machine in
    ppc64)    ./b57ldiagp $@;;
    ppc64le)    ./b57ldiagple $@;;
    i386)     ./b57ldiagi $@;;
    i486)     ./b57ldiagi $@;;
    i586)     ./b57ldiagi $@;;
    i686)     ./b57ldiagi $@;;
    x86_64)   ./b57ldiagi64 $@;;
    aarch64)   ./b57ldiaga $@;;
    *)        echo "Unknown machine architecture - $machine"; exit 1;;
  esac
}

# make sure tg3 is last in list below, used in drvrsRm function above
drvrNames=(tg4 tg3d bcm5700 bcm57diag tg3)
drvrPresent=(0 0 0 0 0)
drvrsPresent=0
drvrRootName="tg3"
drvrRootVersion="3.139i"
drvrPatchName="tg3d"
drvrPatchDir=$drvrPatchName
drvrPatchVersion="0.28"
dirStart=$PWD
TARGET_FILE="/etc/NetworkManager/nm-system-settings.conf"
BIOSDEVNAME="/sbin/biosdevname"
MODPROBE_FILE="/etc/modprobe.conf"
NET_RULES="/etc/udev/rules.d/70-persistent-net.rules"

displayScriptVersion;
drvrsFound;
diagSaveFile
drvrsRm;
if [ $reqDrvrsMake == 1 ]; then
  diagDrvrMake;
fi
diagBiosDevName disable;
diagDrvrInsmod;
diagIgnoreNetworkManager;
diagDrvrIfUpDown up;
diagOpenSSLReLink;
diagOpenSSLCreateSymLink;
if [ $reqDiagRun == 1 ]; then
  diagRun $@;
diagOpenSSLRemoveLink
reqDrvrsRm=1
drvrsFound;
drvrsRm force;
diagRestoreNetworkManager;
diagRestoreSaveFile
fi
diagBiosDevName enable;

